function Piece() {

  this.rotation = 0;
  this.pieceType = Math.round(Math.random() * 6);

  this.typeOne = new Array();
  this.copyOne = new Array();

  this.typeTwo = new Array();
  this.copyTwo = new Array();

  for(var i = 0; (i < 5); i++) {
    this.typeOne[i] = new Array();
    this.copyOne[i] = new Array();
  }

  for(var i = 0; (i < 4); i++) {
    this.copyTwo[i] = new Array();
    this.typeTwo[i] = new Array();
  }
 
  // initialize piece types
  if (this.pieceType < 5) {
    this.xPosition = 4;
    this.yPosition = 0;

    for(var i = 0; (i < 5); i++) {
      for(var j = 0; (j < 5); j++) {
        this.typeOne[i][j] = null;
        this.copyOne[i][j] = null;
      }
    }
  }
  else if (this.pieceType == 5) {
    this.xPosition = 4;
    this.yPosition = -1;

    for(var i = 0; (i < 5); i++) {
      for(var j = 0; (j < 5); j++) {
        this.typeOne[i][j] = null;
        this.copyOne[i][j] = null;
      }
    }
  }
  else if (this.pieceType == 6) {
    this.xPosition = 3;
    this.yPosition = 3;

    for(var i = 0; (i < 4); i++) {
      for(var j = 0; (j < 4); j++) {
        this.typeTwo[i][j] = null;
        this.copyTwo[i][j] = null;
      }
    }
  }

  switch(this.pieceType) {
    /*  
      first 0 - 4 pieces fit into a 3 x 3 matrix indexed by typeOne[x][y] coord of block.
      associations are assigned to the block in the order, up, right, down, left
   
        \ x 0  1  2
        y \
        0   x  x  x  
           
        1   x  x  x 
     
        2   x  x  x
    */
      
    case 0:
      this.size = 5;
      this.typeOne[1][1] = new Block( 0, false, false, true, false);
      this.typeOne[1][2] = new Block( 0, true, true, false, false);
      this.typeOne[2][2] = new Block( 0, false, true, false, true);
      this.typeOne[3][2] = new Block( 0, false, false, false, true);
      break;
    case 1:
      this.size = 5;
      this.typeOne[3][1] = new Block( 1, false, false, true, false);
      this.typeOne[1][2] = new Block( 1, false, true, false, false);
      this.typeOne[2][2] = new Block( 1, false, true, false, true);
      this.typeOne[3][2] = new Block( 1, true, false, false, true);
      break;
    case 2:
      this.size = 5;
      this.typeOne[1][1] = new Block( 2, false, true, false, false);
      this.typeOne[2][1] = new Block( 2, false, false, true, true);
      this.typeOne[2][2] = new Block( 2, true, true, false, false);
      this.typeOne[3][2] = new Block( 2, false, false, false, true);
      break;
    case 3:
      this.size = 5;
      this.typeOne[2][1] = new Block( 3, false, true, true, false);
      this.typeOne[3][1] = new Block( 3, false, false, false, true);
      this.typeOne[2][2] = new Block( 3, true, false, false, true);
      this.typeOne[1][2] = new Block( 3, false, true, false, false);
      break;
    case 4:
      this.size = 5;
      this.typeOne[2][1] = new Block( 4, false, false, true, false);
      this.typeOne[1][2] = new Block( 4, false, true, false, false);
      this.typeOne[2][2] = new Block( 4, true, true, false, true);
      this.typeOne[3][2] = new Block( 4, false, false, false, true);
      break;
      
      /*  
        the last 5 - 6 pieces fit into a 4 x 4 matrix indexed by typeOne[x][y] coord of block,
        these are the long piece and the square.
        associations are assigned to the block in the order, up, right, down, left
   
           \ x 0  1  2  3
          y \
          0    x  x  x  x  

          1    x  x  x  x 

          2    x  x  x  x

          3    x  x  x  x
      */
            
    case 5:
      this.size = 5;
      this.typeOne[1][2] = new Block( 5, false, true, false, false);
      this.typeOne[2][2] = new Block( 5, false, true, false, true);
      this.typeOne[3][2] = new Block( 5, false, true, false, true);
      this.typeOne[4][2] = new Block( 5, false, false, false, true);
      break;
    case 6:
      this.size = 4;
      this.typeTwo[1][1] = new Block( 6, false, true, true, false);
      this.typeTwo[2][1] = new Block( 6, false, false, true, true);
      this.typeTwo[1][2] = new Block( 6, true, true, false, false);
      this.typeTwo[2][2] = new Block( 6, true, false, false, true);
      break;
  }

  if (this.pieceType < 6) {
    for( var i = 0; (i < 5); i++) {
      for( var j = 0; (j < 5); j++) {
        if (this.typeOne[i][j] != null) {
          $('game_board').appendChild(this.typeOne[i][j].div);
        }
      }
    }
  }
  if (this.pieceType == 6) {
    for( var i = 0; (i < 4); i++) {
      for( var j = 0; (j < 4); j++) {
        if (this.typeTwo[i][j] != null) {
          $('game_board').appendChild(this.typeTwo[i][j].div);
        }
      }
    }
  }
}

Piece.prototype.set = function() {

  if (this.pieceType < 6) {
    for( var i = 0; (i < 5); i++) {
      for( var j = 0; (j < 5); j++) {
        if (this.typeOne[i][j] != null) {
          this.typeOne[i][j].setPosition(this.xPosition + i, this.yPosition + j);
        }
      }
    }
  }
  if (this.pieceType == 6) {
    for( var i = 0; (i < 4); i++) {
      for( var j = 0; (j < 4); j++) {
        if (this.typeTwo[i][j] != null) {
          this.typeTwo[i][j].setPosition(this.xPosition + i, this.yPosition + j);
        }
      }
    }
  }
}

Piece.prototype.setTransform = function(_xPosition, _yPosition, _rotation) {
  this.xPosition = _xPosition;
  this.yPosition = _yPosition;
  this.rotation = _rotation;
}

Piece.prototype.drop = function() {
  var i = 0;
  var j = 0;
  var check = false;
  
  while ((i < this.size) && (check == false)) {
    while ((j < this.size) && (check == false)) {
      if (this.size == 4) {
        if (this.typeTwo[i][j] != null) {
          if ((j + this.yPosition + 1) > 22) {
            check = true;
            break;
          }
          if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition + 1] != null) {
            check = true;
            break;
          }
        }
      }
      if (this.size == 5) {
        if (this.typeOne[i][j] != null) {
          if ((j + this.yPosition + 1) > 22) {
            check = true;
            break;
          }
          if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition + 1] != null) {
            check = true;
            break;
          }
        }
      }
      j++;
    }
    j = 0;
    i++;
  }

  if (check == false) {
    this.yPosition++;
    this.moveBlocks();
    return true;
  }
  else {
    return false;
  } 
}

Piece.prototype.rotateLeft = function() {

  var i = 0;
  var j = 0;

  var newX = 0;
  var newY = 0;

  for( i = (this.size - 1); (i >= 0); i--) {
    for( j = 0; (j < this.size); j++) {
      if (this.size == 4) {
        this.copyTwo[newX][newY] = this.typeTwo[i][j];
      } 
      if (this.size == 5) {
        this.copyOne[newX][newY] = this.typeOne[i][j];
      }
      newX++;
    }
    newX = 0;
    newY++;
  }

  i = 0;
  j = 0;

  var check = false;

  while((i < this.size) && (check == false)) {
    while((j < this.size) && (check == false)) {
      if (this.size == 4) {
        if (this.copyTwo[i][j] != null) {
          if ((i + this.xPosition) > 11) {
            check = true;
            break;
          }
          if ((i + this.xPosition) < 0) {
            check = true;
            break;
          }
          if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition] != null) {
            check = true;
            break;
          }
        }
      }
      if (this.size == 5) {
        if (this.copyOne[i][j] != null) {
          if ((i + this.xPosition) > 11) {
            check = true;
            break;
          }
          if ((i + this.xPosition) < 0) {
            check = true;
            break;
          }
          if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition] != null) {
            check = true;
            break;
          }
        }
      }
      j++;
    }
    j = 0;
    i++;
  }

//  $('test_div').innerHTML += 'check was: ' + check + '<br />'; 

  if (check == false) {
    if (this.size == 4) {
      for( i = 0; (i < this.size); i++) {
        for( j = 0; (j < this.size); j++) {
          this.typeTwo[i][j] = this.copyTwo[i][j];
          if (this.typeTwo[i][j] != null) {
            this.typeTwo[i][j].rotateLeft();
          }
          this.copyTwo[i][j] = null;
        } 
      }
    }
    if (this.size == 5) {
      for( i = 0; (i < this.size); i++) {
        for( j = 0; (j < this.size); j++) {
          this.typeOne[i][j] = this.copyOne[i][j];
          if (this.typeOne[i][j] != null) {
            this.typeOne[i][j].rotateLeft();
          }
          this.copyOne[i][j] = null;
        }
      }
    }
    this.moveBlocks();
  }
}

Piece.prototype.rotateRight = function() {

  var i = 0;
  var j = 0;

  var newX = 0;
  var newY = 0;

  for( i = 0; (i < this.size); i++) {
    for( j = (this.size - 1); (j >= 0); j--) {
      if (this.size == 4) {
        this.copyTwo[newX][newY] = this.typeTwo[i][j];
      } 
      if (this.size == 5) {
        this.copyOne[newX][newY] = this.typeOne[i][j];
      }
      newX++;
    }
    newX = 0;
    newY++;
  }

  i = 0;
  j = 0;

  var check = false;

  while((i < this.size) && (check == false)) {
    while((j < this.size) && (check == false)) {
      if (this.size == 4) {
        if (this.copyTwo[i][j] != null) {
          if ((i + this.xPosition) > 11) {
            check = true;
            break;
          }
          if ((i + this.xPosition) < 0) {
            check = true;
            break;
          }
          if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition] != null) {
            check = true;
            break;
          }
        }
      }
      if (this.size == 5) {
        if (this.copyOne[i][j] != null) {
          if ((i + this.xPosition) > 11) {
            check = true;
            break;
          }
          if ((i + this.xPosition) < 0) {
            check = true;
            break;
          }
          if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition] != null) {
            check = true;
            break;
          }
        }
      }
      j++;
    }
    j = 0;
    i++;
  }
  
 //  $('test_div').innerHTML += 'check was: ' + check + '<br />'; 

  if (check == false) {
    if (this.size == 4) {
      for( i = 0; (i < this.size); i++) {
        for (j = 0; (j < this.size); j++) {
          this.typeTwo[i][j] = this.copyTwo[i][j];
          if (this.typeTwo[i][j] != null) {
            this.typeTwo[i][j].rotateRight();
          }
          this.copyTwo[i][j] = null;
        }
      }
    }
    if (this.size == 5) {
      for( i = 0; (i < this.size); i++) {
        for( j = 0; (j < this.size); j++) {
          this.typeOne[i][j] = this.copyOne[i][j];
          if (this.typeOne[i][j] != null) {
            this.typeOne[i][j].rotateRight();
          }
          this.copyOne[i][j] = null;
        }
      }
    }
    this.moveBlocks();
  } 
}

Piece.prototype.moveLeft = function() {
  var i = 0;
  var j = 0;
  var check = false;
  
  while((i < this.size) && (check == false)) {
    while((j < this.size) && (check == false)) {
      if (this.size == 4) {
        if (this.typeTwo[i][j] != null) {
          if ((i + this.xPosition - 1) > 11) {
            check = true;
            break;
          }
          if ((i + this.xPosition -1) < 0) {
            check = true;
            break;
          }
          if (objectGlobals.gameBoard.board[i + this.xPosition - 1][j + this.yPosition] != null) {
            check = true;
            break;
          }
        }
      }
      if (this.size == 5) {
        if (this.typeOne[i][j] != null) {
          if ((i + this.xPosition - 1) > 11) {
            check = true;
            break;
          }
          if ((i + this.xPosition - 1) < 0) {
            check = true;
            break;
          }
          if (objectGlobals.gameBoard.board[i + this.xPosition - 1][j + this.yPosition] != null) {
            check = true;
            break;
          }
        }
      }
      j++;
    }
    j = 0;
    i++;
  }

  if (check == false) {
    this.xPosition--;
    this.moveBlocks();
  } 
}

Piece.prototype.moveRight = function() {
  var i = 0; 
  var j = 0;
  var check = 0;

  while ((i < this.size) && (check == false)) {
    while ((j < this.size) && (check == false)) {
      if (this.size == 4) {
        if (this.typeTwo[i][j] != null) {
          if ((i + this.xPosition + 1) > 11) {
            check = true;
            break;
          }
          if (objectGlobals.gameBoard.board[i + this.xPosition + 1][j + this.yPosition] != null) {
            check = true;
            break;
          }
        }
      }
      if (this.size == 5) {
        if (this.typeOne[i][j] != null) {
          if ((i + this.xPosition + 1) > 11) {
            check = true;
            break;
          }
          if (objectGlobals.gameBoard.board[i + this.xPosition + 1][j + this.yPosition] != null) {
            check = true;
            break;
          }
        }
      }
      j++;
    }
    j = 0;
    i++;
  }

  if (check == false) {
    this.xPosition++;
    this.moveBlocks();
  }
}

Piece.prototype.moveBlocks = function() {
  for( var i = 0; (i < this.size); i++) {
    for( var j = 0; (j < this.size); j++) {
      if (this.size == 4) {
        if (this.typeTwo[i][j] != null) {
          this.typeTwo[i][j].setPosition(this.xPosition + i, this.yPosition + j);
        } 
      }
      if (this.size == 5) {
        if (this.typeOne[i][j] != null) {
          this.typeOne[i][j].setPosition(this.xPosition + i, this.yPosition + j);
        }
      }
    }
  }
}

Piece.prototype.meld = function() {
  for (var i = 0; (i < this.size); i++) {
    for (var j = 0; (j < this.size); j++) {
      if (this.size == 5) {
        if (this.typeOne[i][j] != null) {
          objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition] = this.typeOne[i][j];
          
          if ((this.typeOne[i][j].pipeConnections[0] == true) && ((j + this.yPosition - 1) > -1)) {
            if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition - 1] != null) {
              if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition - 1].pipeConnections[2] == true) {
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition].trueConnections[0] = true;
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition - 1].trueConnections[2] = true;
              }
            }
          }
          if ((this.typeOne[i][j].pipeConnections[1] == true) && ((i + this.xPosition + 1) < 12)) {
            if (objectGlobals.gameBoard.board[i + this.xPosition + 1][j + this.yPosition] != null) {
              if (objectGlobals.gameBoard.board[i + this.xPosition + 1][j + this.yPosition].pipeConnections[3] == true) {
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition].trueConnections[1] = true;
                objectGlobals.gameBoard.board[i + this.xPosition + 1][j + this.yPosition].trueConnections[3] = true;
              }
            }
          }
          if ((this.typeOne[i][j].pipeConnections[2] == true) && ((j + this.yPosition + 1) < 24)) {
            if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition + 1] != null) {
              if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition + 1].pipeConnections[0] == true) {
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition].trueConnections[2] = true;
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition + 1].trueConnections[0] = true;
              }
            }
          }
          if ((this.typeOne[i][j].pipeConnections[3] == true) && ((i + this.xPosition - 1) > -1)) {
            if (objectGlobals.gameBoard.board[i + this.xPosition - 1][j + this.yPosition] != null) {
              if (objectGlobals.gameBoard.board[i + this.xPosition - 1][j + this.yPosition].pipeConnections[1] == true) {
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition].trueConnections[3] = true;
                objectGlobals.gameBoard.board[i + this.xPosition - 1][j + this.yPosition].trueConnections[1] = true;
              }
            }
          }
        }
      }

      if (this.size == 4) {
        if (this.typeTwo[i][j] != null) { 
          objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition] = this.typeTwo[i][j];
          
          if ((this.typeTwo[i][j].pipeConnections[0] == true) && ((j + this.yPosition - 1) > -1)) {
            if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition - 1] != null) {
              if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition - 1].pipeConnections[2] == true) {
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition].trueConnections[0] = true;
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition - 1].trueConnections[2] = true;
              }
            }
          }
          if ((this.typeTwo[i][j].pipeConnections[1] == true) && ((i + this.xPosition + 1) < 12)) {
            if (objectGlobals.gameBoard.board[i + this.xPosition + 1][j + this.yPosition] != null) {
              if (objectGlobals.gameBoard.board[i + this.xPosition + 1][j + this.yPosition].pipeConnections[3] == true) {
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition].trueConnections[1] = true;
                objectGlobals.gameBoard.board[i + this.xPosition + 1][j + this.yPosition].trueConnections[3] = true;
              }
            }
          }
          if ((this.typeTwo[i][j].pipeConnections[2] == true) && ((j + this.yPosition + 1) < 24)) {
            if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition + 1] != null) {
              if (objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition + 1].pipeConnections[0] == true) {
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition].trueConnections[2] = true;
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition + 1].trueConnections[0] = true;
              }
            }
          }
          if ((this.typeTwo[i][j].pipeConnections[3] == true) && ((i + this.xPosition - 1) > -1)) {
            if (objectGlobals.gameBoard.board[i + this.xPosition - 1][j + this.yPosition] != null) {
              if (objectGlobals.gameBoard.board[i + this.xPosition - 1][j + this.yPosition].pipeConnections[1] == true) {
                objectGlobals.gameBoard.board[i + this.xPosition][j + this.yPosition].trueConnections[3] = true;
                objectGlobals.gameBoard.board[i + this.xPosition - 1][j + this.yPosition].trueConnections[1] = true;
              }
            }
          }
        }
      }
    }
  }
  this.debugTrueConnections();
  this.moveBlocks();
}

Piece.prototype.debugTrueConnections = function() {
  if (this.pieceType < 6) {
    for( var i = 0; (i < 5); i++) {
      for( var j = 0; (j < 5); j++) {
        if (this.typeOne[i][j] != null) {
          this.typeOne[i][j].debugTrueConnections();
        }
      }
    }
  }
  if (this.pieceType == 6) {
    for( var i = 0; (i < 4); i++) {
      for( var j = 0; (j < 4); j++) {
        if (this.typeTwo[i][j] != null) {
          this.typeTwo[i][j].debugTrueConnections();
        }
      }
    }
  }
}
